using Microsoft.Phone.Controls.Maps.Design;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Device.Location;
namespace Microsoft.Phone.Controls.Maps
{
	[TypeConverter(typeof(LocationRectConverter))]
	public class LocationRect : IFormattable
	{
		private const double MaxLatitude = 90.0;
		private const double MinLatitude = -90.0;
		private const double MaxLongitude = 180.0;
		private const double MinLongitude = -180.0;
		private GeoCoordinate center;
		private double halfHeight;
		private double halfWidth;
		public double North
		{
			get
			{
				return this.center.get_Latitude() + this.halfHeight;
			}
			set
			{
				this.Init(value, this.West, this.South, this.East);
			}
		}
		public double West
		{
			get
			{
				if (this.halfWidth != 180.0)
				{
					return LocationRect.NormalizeLongitude(this.center.get_Longitude() - this.halfWidth);
				}
				return -180.0;
			}
			set
			{
				this.Init(this.North, value, this.South, this.East);
			}
		}
		public double South
		{
			get
			{
				return this.center.get_Latitude() - this.halfHeight;
			}
			set
			{
				this.Init(this.North, this.West, value, this.East);
			}
		}
		public double East
		{
			get
			{
				if (this.halfWidth != 180.0)
				{
					return LocationRect.NormalizeLongitude(this.center.get_Longitude() + this.halfWidth);
				}
				return 180.0;
			}
			set
			{
				this.Init(this.North, this.West, this.South, value);
			}
		}
		public GeoCoordinate Center
		{
			get
			{
				return this.center;
			}
		}
		public double Width
		{
			get
			{
				return this.halfWidth * 2.0;
			}
		}
		public double Height
		{
			get
			{
				return this.halfHeight * 2.0;
			}
		}
		public GeoCoordinate Northwest
		{
			get
			{
				GeoCoordinate geoCoordinate = new GeoCoordinate();
				geoCoordinate.set_Latitude(this.North);
				geoCoordinate.set_Longitude(this.West);
				return geoCoordinate;
			}
			set
			{
				if (this.center == null)
				{
					this.Init(value.get_Latitude(), value.get_Longitude(), value.get_Latitude(), value.get_Longitude());
					return;
				}
				this.Init(value.get_Latitude(), value.get_Longitude(), this.South, this.East);
			}
		}
		public GeoCoordinate Northeast
		{
			get
			{
				GeoCoordinate geoCoordinate = new GeoCoordinate();
				geoCoordinate.set_Latitude(this.North);
				geoCoordinate.set_Longitude(this.East);
				return geoCoordinate;
			}
			set
			{
				if (this.center == null)
				{
					this.Init(value.get_Latitude(), value.get_Longitude(), value.get_Latitude(), value.get_Longitude());
					return;
				}
				this.Init(value.get_Latitude(), this.West, this.South, value.get_Longitude());
			}
		}
		public GeoCoordinate Southeast
		{
			get
			{
				GeoCoordinate geoCoordinate = new GeoCoordinate();
				geoCoordinate.set_Latitude(this.South);
				geoCoordinate.set_Longitude(this.East);
				return geoCoordinate;
			}
			set
			{
				if (this.center == null)
				{
					this.Init(value.get_Latitude(), value.get_Longitude(), value.get_Latitude(), value.get_Longitude());
					return;
				}
				this.Init(this.North, this.West, value.get_Latitude(), value.get_Longitude());
			}
		}
		public GeoCoordinate Southwest
		{
			get
			{
				GeoCoordinate geoCoordinate = new GeoCoordinate();
				geoCoordinate.set_Latitude(this.South);
				geoCoordinate.set_Longitude(this.West);
				return geoCoordinate;
			}
			set
			{
				if (this.center == null)
				{
					this.Init(value.get_Latitude(), value.get_Longitude(), value.get_Latitude(), value.get_Longitude());
					return;
				}
				this.Init(this.North, value.get_Longitude(), value.get_Latitude(), this.East);
			}
		}
		public LocationRect()
		{
			this.center = new GeoCoordinate(0.0, 0.0);
		}
		public LocationRect(GeoCoordinate center, double width, double height)
		{
			this.center = center;
			this.halfWidth = width / 2.0;
			this.halfHeight = height / 2.0;
		}
		public LocationRect(double north, double west, double south, double east) : this()
		{
			this.Init(north, west, south, east);
		}
		public LocationRect(LocationRect rect)
		{
			this.center = new GeoCoordinate(rect.center.get_Latitude(), rect.center.get_Longitude(), rect.center.get_Altitude());
			this.halfHeight = rect.halfHeight;
			this.halfWidth = rect.halfWidth;
		}
		public static LocationRect CreateLocationRect(params GeoCoordinate[] locations)
		{
			return LocationRect.CreateLocationRect((IEnumerable<GeoCoordinate>)locations);
		}
		public static LocationRect CreateLocationRect(IEnumerable<GeoCoordinate> locations)
		{
			if (locations != null)
			{
				double num = -90.0;
				double num2 = 90.0;
				double num3 = 180.0;
				double num4 = -180.0;
				using (IEnumerator<GeoCoordinate> enumerator = locations.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						GeoCoordinate current = enumerator.get_Current();
						num = Math.Max(num, current.get_Latitude());
						num2 = Math.Min(num2, current.get_Latitude());
						num3 = Math.Min(num3, current.get_Longitude());
						num4 = Math.Max(num4, current.get_Longitude());
					}
				}
				return new LocationRect(num, num3, num2, num4);
			}
			return new LocationRect();
		}
		private void Init(double north, double west, double south, double east)
		{
			if (west > east)
			{
				east += 360.0;
			}
			GeoCoordinate geoCoordinate = new GeoCoordinate();
			geoCoordinate.set_Latitude((south + north) / 2.0);
			geoCoordinate.set_Longitude(LocationRect.NormalizeLongitude((west + east) / 2.0));
			this.center = geoCoordinate;
			this.halfHeight = (north - south) / 2.0;
			this.halfWidth = Math.Abs(east - west) / 2.0;
		}
		string IFormattable.ToString(string format, IFormatProvider provider)
		{
			return string.Format(provider, string.Concat(new string[]
			{
				"{0:",
				format,
				"} {1:",
				format,
				"}"
			}), new object[]
			{
				this.Northwest,
				this.Southeast
			});
		}
		public bool Equals(LocationRect value)
		{
			return this == value;
		}
		public override int GetHashCode()
		{
			return this.center.GetHashCode() ^ this.halfWidth.GetHashCode() ^ this.halfHeight.GetHashCode();
		}
		public override bool Equals(object obj)
		{
			LocationRect locationRect = obj as LocationRect;
			return locationRect != null && (this.center == locationRect.center && this.halfWidth == locationRect.halfWidth) && this.halfHeight == locationRect.halfHeight;
		}
		public bool Intersects(LocationRect rect)
		{
			double num = Math.Abs(this.center.get_Latitude() - rect.center.get_Latitude());
			double num2 = Math.Abs(this.center.get_Longitude() - rect.center.get_Longitude());
			if (num2 > 180.0)
			{
				num2 = 360.0 - num2;
			}
			return num <= this.halfHeight + rect.halfHeight && num2 <= this.halfWidth + rect.halfWidth;
		}
		public LocationRect Intersection(LocationRect rect)
		{
			LocationRect result = new LocationRect();
			if (this.Intersects(rect))
			{
				double num = this.center.get_Longitude() - this.halfWidth;
				double num2 = rect.center.get_Longitude() - rect.halfWidth;
				double num3 = this.center.get_Longitude() + this.halfWidth;
				double num4 = rect.center.get_Longitude() + rect.halfWidth;
				if (Math.Abs(this.center.get_Longitude() - rect.center.get_Longitude()) > 180.0)
				{
					if (this.center.get_Longitude() < rect.center.get_Longitude())
					{
						num += 360.0;
						num3 += 360.0;
					}
					else
					{
						num2 += 360.0;
						num4 += 360.0;
					}
				}
				double num5 = Math.Max(num, num2);
				double num6 = Math.Min(num3, num4);
				double num7 = Math.Min(this.North, rect.North);
				double num8 = Math.Max(this.South, rect.South);
				GeoCoordinate geoCoordinate = new GeoCoordinate();
				geoCoordinate.set_Latitude((num7 + num8) / 2.0);
				geoCoordinate.set_Longitude(LocationRect.NormalizeLongitude((num5 + num6) / 2.0));
				result = new LocationRect(geoCoordinate, num6 - num5, num7 - num8);
			}
			return result;
		}
		public override string ToString()
		{
			return this.ToString(null, null);
		}
		public string ToString(IFormatProvider provider)
		{
			return this.ToString(null, provider);
		}
		private static double NormalizeLongitude(double longitude)
		{
			if (longitude >= -180.0 && longitude <= 180.0)
			{
				return longitude;
			}
			return longitude - Math.Floor((longitude + 180.0) / 360.0) * 360.0;
		}
	}
}
